const TYPES = {
  // STRING: '0',
  NUMBER: '1',
  DATE: '2',
  TIME: '3',
  DATETIME: '4',
  BOOLEAN: '5',
  EMPTY: '20',
  USER: '16',
  UUID: '31',
  URL: '32',
  AREA: '81',
  ADDRESS: '41',
  IMAGE: '51',

  RANGENUMBER: '6',
  RANGEDATE: '7',
  RANGETIME: '8',
  RANGEDATETIME: '9',

  ENUMSTRING: '10',
  ENUMNUMBER: '11',
  ENUMDATE: '12',
  ENUMTIME: '13',
  ENUMDATETIME: '14',
  ENUMBOOLEAN: '15',
  ENUMUUID: '33',
  ENUMURL: '34',
  ENUMUSER: '17',
  ENUMIMAGE: '52',

  RADIOSTRING: '18',
  RADIONUMBER: '19',
  RADIOUSER: '21',
  RADIOUUID: '35',
  RADIOURL: '36',
  RADIOIMAGE: '53',

  COMBSTRING: '20',
  TASK: '60',
  SOURCE: '61',
  SOURCEID: '62',
  GRAPHID: '70',

  ACCTREE: '71',

  DATDLIST: '91',
  CATEGORYCHANGE: '101'
}

const OPERATES = {
  [TYPES.STRING]: {
    equal: {
      name: '等于',
      fns: {
        [TYPES.STRING](a, b) {
          return a === b
        },
        [TYPES.EMPTY](a, b) {
          return a === b && (b == null || b == undefined || b == '')
        }
      },
      sql: {
        [TYPES.STRING](prop, value) {
          return `${prop}='${value}'`
        },
        [TYPES.EMPTY](prop) {
          return `${prop}=null`
        }
      }
    },
    include: {
      name: '包含',
      fns: {
        [TYPES.STRING](a, b) {
          return a.indexOf(b) !== -1
        }
      }
    },
    start: {
      name: '开始为',
      fns: {
        [TYPES.STRING](a, b) {
          return a.startsWith(b)
        }
      }
    },
    end: {
      name: '结束为',
      fns: {
        [TYPES.STRING](a, b) {
          return a.endsWith(b)
        }
      }
    }
  },
  [TYPES.COMBSTRING]: {
    equal: {
      name: '等于',
      fns: {
        [TYPES.COMBSTRING](a, b) {
          return a === b
        },
        [TYPES.EMPTY](a, b) {
          return a === b && (b == null || b == undefined || b == '')
        }
      },
      sql: {
        [TYPES.COMBSTRING](prop, value) {
          return `${prop}='${value}'`
        },
        [TYPES.EMPTY](prop) {
          return `${prop}=null`
        }
      }
    }
  },
  [TYPES.NUMBER]: {
    equal: {
      name: '等于',
      fns: {
        [TYPES.NUMBER](a, b) {
          return a === b
        },
        [TYPES.DATE](a, b) {
          return a === b.toString()
        },
        [TYPES.DATETIME](a, b) {
          return a === b.toString()
        },
        [TYPES.TIME](a, b) {
          return a === b.toString()
        }
      },
      sql: {
        [TYPES.STRING](prop, value) {
          return `${prop}='${value}'`
        },
        [TYPES.EMPTY](prop) {
          return `${prop}=null`
        }
      }
    },
    less: {
      name: '小于',
      fns: {
        [TYPES.NUMBER](a, b) {
          return a < b
        },
        [TYPES.DATE](a, b) {
          return a < b
        },
        [TYPES.DATETIME](a, b) {
          return a < b
        },
        [TYPES.TIME](a, b) {
          return a < b
        }
      }
    },
    more: {
      name: '大于',
      fns: {
        [TYPES.NUMBER](a, b) {
          return a > b
        },
        [TYPES.DATE](a, b) {
          return a > b
        },
        [TYPES.DATETIME](a, b) {
          return a > b
        },
        [TYPES.TIME](a, b) {
          return a > b
        }
      }
    },
    lessorequal: {
      name: '小于等于',
      fns: {
        [TYPES.NUMBER](a, b) {
          return a <= b
        },
        [TYPES.DATE](a, b) {
          return a <= b
        },
        [TYPES.DATETIME](a, b) {
          return a <= b
        },
        [TYPES.TIME](a, b) {
          return a <= b
        }
      }
    },
    moreorequal: {
      name: '大于等于',
      fns: {
        [TYPES.NUMBER](a, b) {
          return a >= b
        },
        [TYPES.DATE](a, b) {
          return a >= b
        },
        [TYPES.DATETIME](a, b) {
          return a >= b
        },
        [TYPES.TIME](a, b) {
          return a >= b
        }
      }
    }
  },
  [TYPES.DATE]: {
    equal: {
      name: '等于',
      fns: {
        [TYPES.NUMBER](a, b) {
          return a === b
        },
        [TYPES.DATE](a, b) {
          return a === b.toString()
        }
      }
    },
    less: {
      name: '小于',
      fns: {
        [TYPES.NUMBER](a, b) {
          return a < b
        },
        [TYPES.DATE](a, b) {
          return a < b
        }
      }
    },
    more: {
      name: '大于',
      fns: {
        [TYPES.NUMBER](a, b) {
          return a > b
        },
        [TYPES.DATE](a, b) {
          return a > b
        }
      }
    },
    lessorequal: {
      name: '小于等于',
      fns: {
        [TYPES.NUMBER](a, b) {
          return a <= b
        },
        [TYPES.DATE](a, b) {
          return a <= b
        }
      }
    },
    moreorequal: {
      name: '大于等于',
      fns: {
        [TYPES.NUMBER](a, b) {
          return a >= b
        },
        [TYPES.DATE](a, b) {
          return a >= b
        }
      }
    }
  },
  [TYPES.TIME]: {
    equal: {
      name: '等于',
      fns: {
        [TYPES.NUMBER](a, b) {
          return a === b
        },
        [TYPES.TIME](a, b) {
          return a === b.toString()
        }
      }
    },
    less: {
      name: '小于',
      fns: {
        [TYPES.NUMBER](a, b) {
          return a < b
        },
        [TYPES.TIME](a, b) {
          return a < b
        }
      }
    },
    more: {
      name: '大于',
      fns: {
        [TYPES.NUMBER](a, b) {
          return a > b
        },
        [TYPES.TIME](a, b) {
          return a > b
        }
      }
    },
    lessorequal: {
      name: '小于等于',
      fns: {
        [TYPES.NUMBER](a, b) {
          return a <= b
        },
        [TYPES.TIME](a, b) {
          return a <= b
        }
      }
    },
    moreorequal: {
      name: '大于等于',
      fns: {
        [TYPES.NUMBER](a, b) {
          return a >= b
        },
        [TYPES.TIME](a, b) {
          return a >= b
        }
      }
    }
  },
  [TYPES.DATETIME]: {
    equal: {
      name: '等于',
      fns: {
        [TYPES.DATETIME](a, b) {
          return a === b.toString()
        }
      }
    },
    less: {
      name: '小于',
      fns: {
        [TYPES.DATETIME](a, b) {
          return a === b.toString()
        }
      }
    },
    more: {
      name: '大于',
      fns: {
        [TYPES.DATETIME](a, b) {
          return a > b
        }
      }
    },
    lessorequal: {
      name: '小于等于',
      fns: {
        [TYPES.NUMBER](a, b) {
          return a <= b
        }
      }
    },
    moreorequal: {
      name: '大于等于',
      fns: {
        [TYPES.DATETIME](a, b) {
          return a >= b
        }
      }
    }
  },
  [TYPES.BOOLEAN]: {
    equal: {
      name: '等于',
      fns: {
        [TYPES.STRING](a, b) {
          return a === b
        },
        [TYPES.BOOLEAN](a, b) {
          return a === b.toString()
        }
      }
    }
  },
  [TYPES.USER]: {
    equal: {
      name: '等于',
      fns: {
        [TYPES.USER](a, b) {
          return a === b
        }
      }
    }
  },
  [TYPES.UUID]: {
    equal: {
      name: '等于',
      fns: {
        [TYPES.UUID](a, b) {
          return a === b
        }
      },
      sql: {
        [TYPES.UUID](prop, value) {
          return `${prop}='${value}'`
        },
        [TYPES.EMPTY](prop) {
          return `${prop}=null`
        }
      }
    }
  },
  [TYPES.URL]: {
    equal: {
      name: '等于',
      fns: {
        [TYPES.URL](a, b) {
          return a === b
        }
      },
      sql: {
        [TYPES.URL](prop, value) {
          return `${prop}='${value}'`
        },
        [TYPES.EMPTY](prop) {
          return `${prop}=null`
        }
      }
    }
  },
  [TYPES.AREA]: {
    equal: {
      name: '等于',
      fns: {
        [TYPES.AREA](a, b) {
          return a === b
        }
      },
      sql: {
        [TYPES.AREA](prop, value) {
          return `${prop}='${value}'`
        },
        [TYPES.EMPTY](prop) {
          return `${prop}=null`
        }
      }
    }
  },
  [TYPES.ADDRESS]: {
    equal: {
      name: '等于',
      fns: {
        [TYPES.ADDRESS](a, b) {
          return a === b
        }
      },
      sql: {
        [TYPES.ADDRESS](prop, value) {
          return `${prop}='${value}'`
        },
        [TYPES.EMPTY](prop) {
          return `${prop}=null`
        }
      }
    }
  },
  [TYPES.IMAGE]: {
    equal: {
      name: '等于',
      fns: {
        [TYPES.IMAGE](a, b) {
          return a === b
        }
      },
      sql: {
        [TYPES.IMAGE](prop, value) {
          return `${prop}='${value}'`
        },
        [TYPES.EMPTY](prop) {
          return `${prop}=null`
        }
      }
    }
  },

  [TYPES.RANGENUMBER]: {
    equal: {
      name: '等于',
      fns: {
        [TYPES.RANGENUMBER](a, b) {
          return a === b
        }
      }
    },
    inner: {
      name: '其中',
      fns: {
        [TYPES.RANGENUMBER](a, b) {
          return a === b
        }
      }
    },
    outer: {
      name: '其外',
      fns: {
        [TYPES.RANGENUMBER](a, b) {
          return a === b
        }
      }
    },
    include: {
      name: '包含',
      fns: {
        [TYPES.NUMBER](a, b) {
          return a === b
        }
      }
    },
    uninclude: {
      name: '不包含',
      fns: {
        [TYPES.NUMBER](a, b) {
          return a === b
        }
      }
    }
  },
  [TYPES.RANGEDATETIME]: {
    equal: {
      name: '等于',
      fns: {
        [TYPES.RANGEDATETIME](a, b) {
          return a === b
        },
        [TYPES.RANGEDATE](a, b) {
          return a === b
        }
      }
    },
    inner: {
      name: '其中',
      fns: {
        [TYPES.RANGEDATETIME](a, b) {
          return a === b
        },
        [TYPES.RANGEDATE](a, b) {
          return a === b
        }
      }
    },
    outer: {
      name: '其外',
      fns: {
        [TYPES.RANGEDATETIME](a, b) {
          return a === b
        },
        [TYPES.RANGEDATE](a, b) {
          return a === b
        }
      }
    },
    include: {
      name: '包含',
      fns: {
        [TYPES.RANGEDATETIME](a, b) {
          return a === b
        }
      }
    },
    uninclude: {
      name: '不包含',
      fns: {
        [TYPES.RANGEDATETIME](a, b) {
          return a === b
        }
      }
    }
  },
  [TYPES.RANGEDATE]: {
    equal: {
      name: '等于',
      fns: {
        [TYPES.RANGEDATE](a, b) {
          return a === b
        }
      }
    },
    inner: {
      name: '其中',
      fns: {
        [TYPES.RANGEDATE](a, b) {
          return a === b
        }
      }
    },
    outer: {
      name: '其外',
      fns: {
        [TYPES.RANGEDATE](a, b) {
          return a === b
        }
      }
    },
    include: {
      name: '包含',
      fns: {
        [TYPES.DATE](a, b) {
          return a === b
        }
      }
    },
    uninclude: {
      name: '不包含',
      fns: {
        [TYPES.DATE](a, b) {
          return a === b
        }
      }
    }
  },
  [TYPES.RANGETIME]: {
    equal: {
      name: '等于',
      fns: {
        [TYPES.RANGETIME](a, b) {
          return a === b
        }
      }
    },
    inner: {
      name: '其中',
      fns: {
        [TYPES.RANGETIME](a, b) {
          return a === b
        }
      }
    },
    outer: {
      name: '其外',
      fns: {
        [TYPES.RANGETIME](a, b) {
          return a === b
        }
      }
    },
    include: {
      name: '包含',
      fns: {
        [TYPES.NUMBER](a, b) {
          return a === b
        }
      }
    },
    uninclude: {
      name: '不包含',
      fns: {
        [TYPES.NUMBER](a, b) {
          return a === b
        }
      }
    }
  },
  [TYPES.RANGENUMBER]: {
    equal: {
      name: '等于',
      fns: {
        [TYPES.NUMBER](a, b) {
          return a === b
        },
        [TYPES.RANGENUMBER](a, b) {
          return a === b
        }
      }
    }
  },

  [TYPES.ENUMSTRING]: {
    equal: {
      name: '等于',
      fns: {
        [TYPES.ENUMSTRING](a, b) {
          if (Array.isArray(a)) {
            return a.length === b.length && a.find(c => b.includes(c)) != undefined
          } else {
            return a === b
          }
        }
      },
      sql: {
        [TYPES.STRING](prop, value) {
          return `${prop}='${value}'`
        },
        [TYPES.EMPTY](prop) {
          return `${prop}=null`
        }
      }
    },
    include: {
      name: '包含',
      fns: {
        [TYPES.STRING](a, b) {
          return a === b
        }
      }
    },
    uninclude: {
      name: '不包含',
      fns: {
        [TYPES.STRING](a, b) {
          return a === b
        }
      }
    }
  },
  [TYPES.ENUMNUMBER]: {
    include: {
      name: '包含',
      fns: {
        [TYPES.NUMBER](a, b) {
          return a === b
        },
        [TYPES.TIME](a, b) {
          return a === b
        }
      }
    },
    uninclude: {
      name: '不包含',
      fns: {
        [TYPES.NUMBER](a, b) {
          return a === b
        },
        [TYPES.TIME](a, b) {
          return a === b
        }
      }
    }
  },
  [TYPES.ENUMDATE]: {
    include: {
      name: '包含',
      fns: {
        [TYPES.DATE](a, b) {
          return a === b
        }
      }
    },
    uninclude: {
      name: '不包含',
      fns: {
        [TYPES.DATE](a, b) {
          return a === b
        }
      }
    }
  },
  [TYPES.ENUMTIME]: {
    include: {
      name: '包含',
      fns: {
        [TYPES.TIME](a, b) {
          return a === b
        }
      }
    },
    uninclude: {
      name: '不包含',
      fns: {
        [TYPES.TIME](a, b) {
          return a === b
        }
      }
    }
  },
  [TYPES.ENUMDATETIME]: {
    include: {
      name: '包含',
      fns: {
        [TYPES.DATETIME](a, b) {
          return a === b
        }
      }
    },
    uninclude: {
      name: '不包含',
      fns: {
        [TYPES.DATETIME](a, b) {
          return a === b
        }
      }
    }
  },
  [TYPES.ENUMBOOLEAN]: {
    include: {
      name: '包含',
      fns: {
        [TYPES.BOOLEAN](a, b) {
          return a === b
        }
      }
    },
    uninclude: {
      name: '不包含',
      fns: {
        [TYPES.BOOLEAN](a, b) {
          return a === b
        }
      }
    }
  },
  [TYPES.ENUMUSER]: {
    equal: {
      name: '等于',
      fns: {
        [TYPES.ENUMUSER](a, b) {
          return a === b
        }
      }
    },
    include: {
      name: '包含',
      fns: {
        [TYPES.USER](a, b) {
          return a.includes(b)
        }
      }
    },
    uninclude: {
      name: '不包含',
      fns: {
        [TYPES.USER](a, b) {
          return !a.includes(b)
        }
      }
    }
  },
  [TYPES.ENUMUUID]: {
    equal: {
      name: '等于',
      fns: {
        [TYPES.ENUMUUID](a, b) {
          return a === b
        }
      }
    },
    include: {
      name: '包含',
      fns: {
        [TYPES.UUID](a, b) {
          return a.includes(b)
        }
      }
    },
    uninclude: {
      name: '不包含',
      fns: {
        [TYPES.UUID](a, b) {
          return !a.includes(b)
        }
      }
    }
  },
  [TYPES.ENUMURL]: {
    equal: {
      name: '等于',
      fns: {
        [TYPES.ENUMURL](a, b) {
          return a === b
        }
      }
    },
    include: {
      name: '包含',
      fns: {
        [TYPES.URL](a, b) {
          return a.includes(b)
        }
      }
    },
    uninclude: {
      name: '不包含',
      fns: {
        [TYPES.URL](a, b) {
          return !a.includes(b)
        }
      }
    }
  },
  [TYPES.ENUMIMAGE]: {
    equal: {
      name: '等于',
      fns: {
        [TYPES.ENUMIMAGE](a, b) {
          return a === b
        }
      }
    },
    include: {
      name: '包含',
      fns: {
        [TYPES.IMAGE](a, b) {
          return a.includes(b)
        }
      }
    },
    uninclude: {
      name: '不包含',
      fns: {
        [TYPES.IMAGE](a, b) {
          return !a.includes(b)
        }
      }
    }
  },

  [TYPES.RADIOSTRING]: {
    equal: {
      name: '等于',
      fns: {
        [TYPES.STRING](a, b) {
          return a === b
        },
        [TYPES.RADIOSTRING](a, b) {
          return a === b
        }
      },
      sql: {
        [TYPES.STRING](prop, value) {
          return `${prop}='${value}'`
        },
        [TYPES.RADIOSTRING](prop, value) {
          return `${prop}='${value}'`
        }
      }
    }
  },
  [TYPES.RADIONUMBER]: {
    equal: {
      name: '等于',
      fns: {
        [TYPES.NUMBER](a, b) {
          return a === b
        },
        [TYPES.RADIONUMBER](a, b) {
          return a === b
        }
      },
      sql: {
        [TYPES.NUMBER](prop, value) {
          return `${prop}='${value}'`
        },
        [TYPES.RADIONUMBER](prop, value) {
          return `${prop}='${value}'`
        }
      }
    }
  },
  [TYPES.RADIOUSER]: {
    equal: {
      name: '等于',
      fns: {
        [TYPES.USER](a, b) {
          return a === b
        },
        [TYPES.RADIOUSER](a, b) {
          return a === b
        }
      },
      sql: {
        [TYPES.USER](prop, value) {
          return `${prop}='${value}'`
        },
        [TYPES.RADIOUSER](prop, value) {
          return `${prop}='${value}'`
        }
      }
    }
  },
  [TYPES.RADIOUUID]: {
    equal: {
      name: '等于',
      fns: {
        [TYPES.UUID](a, b) {
          return a === b
        },
        [TYPES.RADIOUUID](a, b) {
          return a === b
        }
      },
      sql: {
        [TYPES.UUID](prop, value) {
          return `${prop}='${value}'`
        },
        [TYPES.RADIOUUID](prop, value) {
          return `${prop}='${value}'`
        }
      }
    }
  },
  [TYPES.RADIOURL]: {
    equal: {
      name: '等于',
      fns: {
        [TYPES.URL](a, b) {
          return a === b
        },
        [TYPES.RADIOURL](a, b) {
          return a === b
        }
      },
      sql: {
        [TYPES.URL](prop, value) {
          return `${prop}='${value}'`
        },
        [TYPES.RADIOURL](prop, value) {
          return `${prop}='${value}'`
        }
      }
    }
  },
  [TYPES.RADIOIMAGE]: {
    equal: {
      name: '等于',
      fns: {
        [TYPES.IMAGE](a, b) {
          return a === b
        },
        [TYPES.RADIOIMAGE](a, b) {
          return a === b
        }
      },
      sql: {
        [TYPES.IMAGE](prop, value) {
          return `${prop}='${value}'`
        },
        [TYPES.RADIOIMAGE](prop, value) {
          return `${prop}='${value}'`
        }
      }
    }
  },
  [TYPES.TASK]: {
    equal: {
      name: '等于',
      fns: {
        [TYPES.TASK](a, b) {
          return a === b
        }
      },
      sql: {
        [TYPES.TASK](prop, value) {
          return `${prop}='${value}'`
        }
      }
    }
  },
  [TYPES.SOURCEID]: {
    equal: {
      name: '等于',
      fns: {
        [TYPES.TASK](a, b) {
          return a === b
        }
      },
      sql: {
        [TYPES.TASK](prop, value) {
          return `${prop}='${value}'`
        }
      }
    }
  },
  [TYPES.SOURCE]: {
    equal: {
      name: '等于',
      fns: {
        [TYPES.SOURCE](a, b) {
          if (Array.isArray(a)) {
            return a.length === b.length && a.find(c => b.includes(c)) != undefined
          } else {
            return a === b
          }
        }
      },
      sql: {
        [TYPES.SOURCE](prop, value) {
          return `${prop}='${value}'`
        },
        [TYPES.EMPTY](prop) {
          return `${prop}=null`
        }
      }
    },
    include: {
      name: '包含',
      fns: {
        [TYPES.SOURCE](a, b) {
          return b.find(c => !a.includes(c)) == undefined
        }
      }
    },
    uninclude: {
      name: '不包含',
      fns: {
        [TYPES.SOURCE](a, b) {
          return b.find(c => !a.includes(c)) != undefined
        }
      }
    }
  },
  [TYPES.GRAPHID]: {
    equal: {
      name: '等于',
      fns: {
        [TYPES.GRAPHID](a, b) {
          return a === b
        }
      },
      sql: {
        [TYPES.GRAPHID](prop, value) {
          return `${prop}='${value}'`
        }
      }
    }
  },
  [TYPES.ACCTREE]: {
    equal: {
      name: '等于',
      fns: {
        [TYPES.GRAPHID](a, b) {
          return a === b
        }
      },
      sql: {
        [TYPES.GRAPHID](prop, value) {
          return `${prop}='${value}'`
        }
      }
    }
  },
  [TYPES.DATDLIST]: {
    equal: {
      name: '等于',
      fns: {
        [TYPES.DATDLIST](a, b) {
          return a === b
        }
      },
      sql: {
        [TYPES.DATDLIST](prop, value) {
          return `${prop}='${value}'`
        },
        [TYPES.EMPTY](prop) {
          return `${prop}=null`
        }
      }
    }
  },
  [TYPES.CATEGORYCHANGE]: {
    change: {
      name: '变化',
      fns: {
        [TYPES.CATEGORYCHANGE]() {
          return true
        }
      }
    },
    equal: {
      name: '等于',
      fns: {
        [TYPES.CATEGORYCHANGE](a, b) {
          return a === b
        }
        // [TYPES.STRING](a, b) {
        //   return a === b
        // },
        // [TYPES.EMPTY](a, b) {
        //   return a === b && (b == null || b == undefined || b == '')
        // }
      },
      sql: {
        [TYPES.CATEGORYCHANGE](prop, value) {
          return `${prop}='${value}'`
        },
        [TYPES.EMPTY](prop) {
          return `${prop}=null`
        }
      }
    }
  }
}

const VALUETYPES = {
  ...TYPES,
  OPERATES
}

export default {
  OPERATES,
  VALUETYPES,
  getTypeOperators(type) {
    return Reflect.ownKeys(OPERATES[type]).map(operate => {
      return {
        name: OPERATES[type][operate].name,
        value: operate,
        accepts: Reflect.ownKeys(OPERATES[type][operate].fns)
      }
    })
  },
  getTypeSQLOperators(type) {
    return Reflect.ownKeys(OPERATES[type]).filter(operate => {
      return OPERATES[type][operate].sql && Reflect.ownKeys(OPERATES[type][operate].sql).length > 0
    }).map(operate => {
      return {
        name: OPERATES[type][operate].name,
        value: operate,
        accepts: Reflect.ownKeys(OPERATES[type][operate].sql)
      }
    })
  },
  getTypeAccepts(type, operate) {
    const t = this.getTypeOperators(type).find(a => a.value === operate)
    if (t) {
      return t.accepts
    } else {
      return []
    }
  },
  getTypeSQLAccepts(type, operate) {
    const t = this.getTypeOperators(type).find(a => a.value === operate)
    if (t) {
      return t.accepts
    } else {
      return []
    }
  },
  invokeOperate({ operate, lvalue, lvalueType, rvalue, rvalueType, data }) {
    if (OPERATES[lvalueType] && OPERATES[lvalueType][operate] && OPERATES[lvalueType][operate].fns[rvalueType]) {
      return OPERATES[lvalueType][operate].fns[rvalueType](lvalue, rvalue, data)
    }
    return null
  },
  getOperateSQL({ prop, lvalueType, rvalueType, rvalue, operate, prefix = '', suffix = '' }) {
    if (OPERATES[lvalueType] && OPERATES[lvalueType][operate] && OPERATES[lvalueType][operate].sql[rvalueType]) {
      return OPERATES[lvalueType][operate].sql[rvalueType](`${prefix}${prop}${suffix}`, rvalue)
    }
  },
  getFilterSQL({ list, prefix, suffix }) {
    const or = {}
    list.forEach(a => {
      if (!or[a.group]) {
        or[a.group] = []
      }
      or[a.group].push({
        prop: a.key,
        rvalueType: a.rvalueType,
        lvalueType: a.lvalueType,
        rvalue: a.value,
        operate: a.operator
      })
    })
    return Reflect.ownKeys(or).map(group => {
      const str = or[group].map(item => {
        return this.getOperateSQL({ ...item, prefix, suffix })
      }).join(' and ')
      return `(${str})`
    }).join(' or ')
  },
  isTypeOf(type, target) {
    return type === target || OPERATES[target] && Reflect.ownKeys(OPERATES[target]).find(a => OPERATES[target][a].fns[type] !== undefined) !== undefined
  }
}
